//
// Created by jyh on 2021/8/1.
//
#include "Antatx.h"
#include "./Com.h"

void Antatx_m_resetMem(struct Antatx* AX){
    AX->nfreq = 0;
    AX->zen1 = AX->zen2 = AX->dzen = AX->dazi = 0;
    memset(AX->antnam,0,sizeof(AX->antnam));
    memset(AX->antnum,0,sizeof(AX->antnum));
    memset(AX->freq,0,sizeof(AX->freq));
    memset(AX->pcv,0,sizeof(AX->pcv));
    memset(AX->neu,0,sizeof(AX->neu));
}
int Antatx_m_getAnt(struct Antatx* AX, const char* ctype, int* nfreq, char freq[MAXSYS][MAXFREQ][LEN_FREQ],
                     double fjd_beg, double fjd_end, const char* antnam, const char* antnum,
                     double enu_sat[MAXFREQ][3],double enu_sit[MAXSYS][MAXFREQ][3]){
    int isys,i,iref_g;
    Antatx_m_resetMem(AX);
    strcpy(AX->antnam,antnam);
    strcpy(AX->antnum,antnum);

    if(strstr(antnam,"ANTNONE")){
        memset(AX->neu,0,sizeof(AX->neu));
        memset(AX->pcv,0,sizeof(AX->pcv));
    }else{
        if(!Antatx_m_rdatx(AX, nfreq,freq,fjd_beg,fjd_end))
            return 0;
    }
    /// is not suitable for Tri-frequency here,there is bug in it
    iref_g = index_string(SYS,'G');
    if(strstr(ctype,"SITE")){
        for(isys = 0;isys < MAXSYS;isys++){
            for(i = 0; i < nfreq[isys];i++){
                if(len_trim(AX->freq[isys][i]) == 0){
                    /// 如果GPS有这个频点的观测量的话，即使用GPS作为PCO
                    if(len_trim(AX->freq[iref_g][i]) != 0){
                        enu_sit[isys][i][0] =
                                AX->neu[iref_g][i][1];
                        enu_sit[isys][i][1] =
                                AX->neu[iref_g][i][0];
                        enu_sit[isys][i][2] =
                                AX->neu[iref_g][i][2];
                    }else{
                        /// 如果GPS没有这个频点的观测量的话，就用GPS第一个频点的作为PCO
                        enu_sit[isys][i][0] =
                                AX->neu[iref_g][0][1];
                        enu_sit[isys][i][1] =
                                AX->neu[iref_g][0][0];
                        enu_sit[isys][i][2] =
                                AX->neu[iref_g][0][2];
                    }
                }else{
                    /// 如果内存里有这个频点的PCO的话，直接用内存的
                    enu_sit[isys][i][0] = AX->neu[isys][i][1];
                    enu_sit[isys][i][1] = AX->neu[isys][i][0];
                    enu_sit[isys][i][2] = AX->neu[isys][i][2];
                }
            }
        }
    }else{
        isys = index_string(SYS,ctype[0]);
        for(i = 0; i < MAXFREQ;i++){
            enu_sat[i][0] = AX->neu[isys][i][0];
            enu_sat[i][1] = AX->neu[isys][i][1];
            enu_sat[i][2] = AX->neu[isys][i][2];
        }
    }
    return 1;
}
void Antatx_s_checkdata(char* line,char* format){
    int count;
    int i, j, index, tmp;
    double step;
    char value[128][8];
    char varword[128] = { '\0' };
    char* pStr = NULL;
    for (i = 0; i < 128; i++)
        for (j = 0; j < 8; j++)
            value[i][j] = '\0';
    split_string(true, format, ' ', ' ', '%', &count, (char*)value, 8);
    index = 0;
    for (i = 0; i < count; i++) {
        strncpy(varword, "\0", 128);
        if (strstr(value[i], "*") == NULL) {
            if (strstr(value[i], "s") != NULL) {
                substringEx(varword, value[i], 0, index_string(value[i], 's'));
                if (len_trim(varword) == 0) {
                    printf(
                            "***ERROR(checkdata): please make clear the length of the format s!\n");
                    exit(1);
                }
                step = atof(varword);
                substringEx(varword, line, index, (int) step);
                pStr = left_justify_string(varword);
                for (j = 0; j < len_trim(pStr); j++) {
                    if (pStr[j] == 32)
                        line[index + j] = 126;
                }
                index += (int) step;

            }
            if (strstr(value[i], "d") != NULL) {
                substringEx(varword, value[i], 0, index_string(value[i], 'd'));
                if (len_trim(varword) == 0) {
                    printf(
                            "***ERROR(checkdata): please make clear the length of the format d!\n");
                    exit(1);
                }

                step = atof(varword);
                substringEx(varword, line, index, (int) step);
                pStr = left_justify_string(varword);
                if (len_trim(pStr) != (int) step) {
                    tmp = (int) step - len_trim(pStr);
                    if ((j = index_string(pStr, '-')) != -1) {
                        line[index] = '-';
                        line[index + tmp] = '0';
                    } else
                        line[index] = '0';

                    for (j = 1; j < tmp; j++) {
                        line[index + j] = '0';
                    }
                }
                index += (int) step;
            }
            if (strstr(value[i], "f") != NULL) {
                if (strstr(value[i], "lf") != NULL)
                    substringEx(varword, value[i], 0,
                                index_string(value[i], 'l'));
                else
                    substringEx(varword, value[i], 0,
                                index_string(value[i], 'f'));
                if (len_trim(varword) == 0) {
                    printf(
                            "***ERROR(checkdata): please make clear the length of the format f!\n");
                    exit(1);
                }
                step = atof(varword);
                substringEx(varword, line, index, (int) step);
                pStr = left_justify_string(varword);
                if (len_trim(pStr) != (int) step) {
                    tmp = (int) step - len_trim(pStr);
                    if ((j = index_string(pStr, '-')) != -1) {
                        line[index] = '-';
                        line[index + tmp] = '0';
                    } else
                        line[index] = '0';
                    for (j = 1; j < tmp; j++) {
                        line[index + j] = '0';
                    }
                }
                index += (int) step;
            }
            if (strstr(value[i], "c") != NULL) {
                substringEx(varword, value[i], 0, index_string(value[i], 'c'));
                if (len_trim(varword) == 0) {
                    printf(
                            "***ERROR(checkdata): please make clear the length of the format c!\n");
                    exit(1);
                }
                step = atof(varword);
                substringEx(varword, line, index, (int) step);
                if (len_trim(varword) == 0) {
                    line[index + (int) step - 1] = 0;
                }
                index += (int) step;
            }

        } else {
            substringEx(varword, value[i], index_string(value[i], '*') + 1,
                        strlen(value[i]) - 2);
            if (len_trim(varword) == 0)
                step = 1;
            else
                step = atof(varword);
            index += (int) step;
        }
    }
    format[strlen(format) - 1] = '\0';
}
int Antatx_s_rdSvnav(const char* cprn,double mjd,char* blk,double* mass,int* ifreq,double* xyz,char* sid,char* svn){
    char line[LEN_STRING+1];
    char strline[1024],format[1024],slr[256] = {0};
    char typ[24],cid[24];
    char prn[LEN_PRN];
    int iy, im, id, ih, imin, isec;
    int ky, km, kd, kh, kmin, ksec;
    int i, iq;
    double imass, enu[3], mjds, mjde;
    //map<string, string>::iterator itr;
    FILE* in;
    // if ((in=fopen(DLY.mTable.satnav, "r"))==NULL){
    //     printf("file = %s,can't accsss satnav file", DLY.mTable.satnav);
    //     exit(1);
    // }
    if ((in=fopen("./gnss.sit_out", "r"))==NULL){
        printf("file = %s,can't accsss satnav file", DLY.mTable.satnav);
        exit(1);
    }
    while (fgets(line, LEN_STRING, in)){
        if(strstr(line,"PART 1")) break;
    }
    for(i = 0 ;i < 5; i ++) fgets(line, LEN_STRING, in);
    strcpy(format, "%3s%*2c%3s%*2c%20s%*2c%9s%*2c%4d%*c%2d%*c%2d%*c%2d%"
                   "*c%2d%*c%2d%*2c%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d%*2c%6lf%*2c%4d");
    int lfind = 0;
    while (fgets(line, LEN_STRING, in)){
        if(strstr(line,"PART 2")) break;
        strcpy(strline,line);
        Antatx_s_checkdata(strline, format);
        sscanf(strline, format, prn, slr, typ, cid, &iy, &im, &id, &ih, &imin,
               &isec, &ky, &km, &kd, &kh, &kmin, &ksec, &imass, &iq);
        if(strstr(prn,cprn) == NULL)
            continue;

        mjds = md_julday(iy, im, id) + ih / 24.0 + imin / 1440.0
               + isec / 86400.0;
        if (ky == 0)
            mjde = mjd + 1;
        else
            mjde = md_julday(ky, km, kd) + kh / 24.0 + kmin / 1440.0
                   + ksec / 86400.0;
        if (mjd > mjds && mjd < mjde) {
            lfind = true;
            break;
        }
    }
    if(!lfind){
        printf("cprn = %s,file = %s,satellite not found in svnav file",cprn,DLY.mTable.satnav);
        fclose(in);
        return 0;
    }else{
        i = index_string(typ, '~');
        if(-1 != i)
            typ[i] = ' ';
        strcpy(blk, typ);
        *ifreq = iq;
        *mass = imass;
        sscanf(cid, "%4d%*c%3d", &iy, &im);
        if (iy > 2000)
            iy = iy - 2000;
        else
            iy = iy - 1900;
        strcpy(svn,slr);
        sprintf(sid, "%02d%03d%02d", iy, im, cid[8] - 65 + 1);
    }
    while (fgets(line, LEN_STRING, in)){
        if(strstr(line,"PART 2")) break;
    }
    for(i = 0 ;i < 5; i ++) fgets(line, LEN_STRING, in);
    lfind = 0;
    strcpy(format, "%3s%*2c%3s%*3c%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d%*2c%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d%*3c%10lf%10lf%10lf");

    for(i = 0; i < 3;i++) xyz[i] = 0;

    while (fgets(line, LEN_STRING, in)){
        strcpy(strline,line);
        Antatx_s_checkdata(strline,format);
        sscanf(strline, format, prn, slr, &iy, &im, &id, &ih, &imin, &isec, &ky,
               &km, &kd, &kh, &kmin, &ksec, enu, enu + 1, enu + 2);
        if (strstr(slr, "SLR") == NULL)
            continue;
        if (strstr(prn, cprn) == NULL)
            continue;

        mjds = md_julday(iy, im, id) + ih / 24.0 + imin / 1440.0
               + isec / 86400.0;
        if (ky == 0)
            mjde = mjd + 1;
        else
            mjde = md_julday(ky, km, kd) + kh / 24.0 + kmin / 1440.0
                   + ksec / 86400.0;
        if (mjd > mjds && mjd < mjde) {
            lfind = true;
            break;
        }
    }
    if(lfind){
        for(i = 0; i <3;i++)
            xyz[i] = enu[i];
    }
    fclose(in);
    return 1;
}
int Antatx_s_antnam(const char* sitname, const char* anttyp, char* antname){
    char cmain[256] = {0}, buf[256] = {0};
    char *line, *key;
    int lfound = 0;
    FILE *in;
    line=calloc(LEN_STRING+1,sizeof(char));
    key=calloc(256+1,sizeof(char));
    //map<string, string>::iterator itr;
    if ((in=fopen(DLY.mTable.antnam, "r"))==NULL){
        printf("file = %s,can't accsss satnav file", DLY.mTable.antnam);
        exit(1);
    }
    while (fgets(line, LEN_STRING, in)){
        strncpy(key,line+5,strlen(line)-5);
        //key = line.substr(5,line.size() - 5);
        if(strstr(line,"MAIN"))
            substringEx(cmain,line,5,strlen(line) - 5);
        if(strstr(key,anttyp)){
            strcpy(antname,cmain);
            lfound = 1;
            break;
        }
    }
    if(!lfound){
        printf("anttyp = %s,sitname = %s,antenna unknown",anttyp,sitname);
        fclose(in);
        return 0;
    }
    fclose(in);
    free(key);
    free(line);
    return 1;
}
int Antatx_m_rdatx(struct Antatx* AX, int nfreq[MAXSYS], char freq[MAXSYS][MAXFREQ][LEN_FREQ], double fjd_beg, double fjd_end) {
    char line[LEN_STRING+1];
    char tmp[1024], atxtyp = ' ';
    bool lfind = false;
    double fjd0, fjd1, sod;
    int iy, imon, id, ih, im;
    int i, j, k, l, ncol, nrow, irow, isys;
    FILE *in;
    fpos_t pos;
    //map<string, string>::iterator itr;
    //Deploy *dly = Controller::s_getInstance()->m_getConfigure();

    if ((in=fopen(DLY.mTable.antpcv, "r"))==NULL) {
        printf("file = %s,can't accsss satnav file", DLY.mTable.satnav);
        exit(1);
    }
    while (fgets(line, LEN_STRING, in)) {
        if (strstr(line, "PCV TYPE / REFANT")) {
            atxtyp = line[0];
            break;
        }
        if (strstr(line, "END OF HEADER"))
            break;
    }
    if (atxtyp != 'A') {
        printf("type = %c,atxfile = %s,should refer absolute antenna mode in atxfile", atxtyp, DLY.mTable.antpcv);
        fclose(in);
        return 0;
    }
    // each time call this function,the file should be reset
    lfind = false;
    while (fgets(line, LEN_STRING, in)) {
        while (strstr(line, "TYPE / SERIAL NO") == NULL) {
            fgets(line, LEN_STRING, in);
            if (!line) {
                printf("antnam = %s,antnum = %s,atxfile = %s,no definition for antenna in atxfile", AX->antnam, AX->antnum, DLY.mTable.antpcv);
                fclose(in);
                return 0;
            }
        }
        if (strstr(line, AX->antnam) == NULL) {
            continue;
        }
        j = len_trim(AX->antnum);
        if (j != 0) {
            substringEx(tmp, line, 20, 3);
            if (strstr(AX->antnum, tmp) == NULL) {
                continue;
            }
        }
        AX->dazi = 0.0;
        AX->dzen = 0.0;
        AX->nfreq = 0;
        fjd0 = 0;
        fjd1 = 1E10;
        while (strstr(line, "START OF FREQUENCY") == NULL) {
            fgetpos(in, &pos);
            fgets(line, LEN_STRING, in);
            if (strstr(line, "DAZI") != NULL)
                sscanf(line, "%lf", &AX->dazi);
            else if (strstr(line, "ZEN1 / ZEN2 / DZEN") != NULL)
                sscanf(line, "%lf%lf%lf", &AX->zen1, &AX->zen2, &AX->dzen);
            else if (strstr(line, "VALID FROM") != NULL) {
                sscanf(line, "%d%d%d%d%d%lf", &iy, &imon, &id, &ih, &im, &sod);
                fjd0 = md_julday(iy, imon, id) + ih / 24.0 + im / 1440.0 + sod / 86400.0;
            } else if (strstr(line, "VALID UNTIL") != NULL) {
                sscanf(line, "%d%d%d%d%d%lf", &iy, &imon, &id, &ih, &im, &sod);
                fjd1 = md_julday(iy, imon, id) + ih / 24.0 + im / 1440.0 + sod / 86400.0;
            } else if (strstr(line, "# OF FREQUENCIES") != NULL)
                sscanf(line, "%d", &AX->nfreq);
        }
        if ((fjd_beg - fjd0) > MAXWND && (fjd1 - fjd_end) > MAXWND) {
            lfind = true;
            break;
        } else
        continue;
    }
    if (!lfind) {
        printf("antnam = %s,antnum = %s,atxfile = %s,no definition for antenna in atxfile", AX->antnam, AX->antnum, DLY.mTable.antpcv);
        fclose(in);
        return 0;
    }
    fsetpos(in, &pos);
    ncol = 0;
    nrow = 1;
    if (AX->dazi != 0)
        nrow = (int) (360.0 / AX->dazi) + 2;
    if (AX->dzen != 0)
        ncol = (int) ((AX->zen2 - AX->zen1) / AX->dzen) + 1;
    for (i = 0; i < AX->nfreq; i++) {
        memset(line, 0, sizeof(char)*1025);
        while (strstr(line, "START OF FREQUENCY") == NULL) {
            fgets(line, LEN_STRING, in);
            if (strstr(line, "END OF ANTENNA") != NULL) {
                printf("antnam = %s,antnum = %s,atxfile = %s,frequency not found", AX->antnam, AX->antnum, DLY.mTable.antpcv);
                fclose(in);
                return 0;
            }
        }
        k = -1;
        isys = -1;
        if (strstr(line, "G01") != NULL) {
            isys = index_string(SYS, 'G');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L1");
        } else if (strstr(line, "G02") != NULL) {
            isys = index_string(SYS, 'G');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L2");
        } else if (strstr(line, "G05") != NULL) {
            isys = index_string(SYS, 'G');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L5");
        } else if (strstr(line, "R01") != NULL) {
            isys = index_string(SYS, 'R');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L1");
        } else if (strstr(line, "R02") != NULL) {
            isys = index_string(SYS, 'R');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L2");
        } else if (strstr(line, "E01") != NULL) {
            isys = index_string(SYS, 'E');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L1");
        } else if (strstr(line, "E5a") != NULL) {
            isys = index_string(SYS, 'E');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L5");
        } else if (strstr(line, "E5b") != NULL) {
            isys = index_string(SYS, 'E');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L7");
        } else if (strstr(line, "E05") != NULL) {
            isys = index_string(SYS, 'E');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L8");
        } else if (strstr(line, "E06") != NULL) {
            isys = index_string(SYS, 'E');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L6");
        } else if (strstr(line, "B02") != NULL || strstr(line, "C02") != NULL) {
            isys = index_string(SYS, 'C');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L2");
        } else if (strstr(line, "B07") != NULL || strstr(line, "C07") != NULL) {
            isys = index_string(SYS, 'C');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L7");
        } else if (strstr(line, "B06") != NULL || strstr(line, "C06") != NULL) {
            isys = index_string(SYS, 'C');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L6");
        } else if (strstr(line, "B01") != NULL || strstr(line, "C01") != NULL) {
            isys = index_string(SYS, 'C');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L1");
        } else if (strstr(line, "B05") != NULL || strstr(line, "C05") != NULL) {
            isys = index_string(SYS, 'C');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L5");
        } else if (strstr(line, "B08") != NULL || strstr(line, "C08") != NULL) {
            isys = index_string(SYS, 'C');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L8");
        } else if (strstr(line, "J01") != NULL) {
            isys = index_string(SYS, 'J');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L1");
        } else if (strstr(line, "J02") != NULL) {
            isys = index_string(SYS, 'J');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L2");
        } else if (strstr(line, "J05") != NULL) {
            isys = index_string(SYS, 'J');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L5");
        } else if (strstr(line, "J06") != NULL) {
            isys = index_string(SYS, 'J');
            k = pointer_charstr(nfreq[isys], LEN_FREQ, (char*) freq[isys], "L6");
        }
        if (k == -1 || isys == -1)
            continue;
        substringEx(tmp, line, 3, 3);
        strncpy(AX->freq[isys][k], tmp, 3);
        irow = -1;
        while (true) {
            fgets(line, LEN_STRING, in);
            if (strstr(line, "END OF FREQUENCY") != NULL)
                break;
            if (strstr(line, "NORTH / EAST / UP") != NULL) {
                sscanf(line, "%lf%lf%lf", AX->neu[isys][k] + 0, AX->neu[isys][k] + 1, AX->neu[isys][k] + 2);
                //convert unit from mm to m
                for (j = 0; j < 3; j++)
                    AX->neu[isys][k][j] = AX->neu[isys][k][j] * 1e-3;
            } else {
                irow = irow + 1;
                for (j = 0; j < ncol; j++) {
                    substringEx(tmp, line, 8 + 8 * j, 8);
                    AX->pcv[isys][k][irow][j] = atof(tmp);
                }
            }
        }
        if ((irow + 1) != nrow) {
            printf("antnam = %s,antnum = %s,atxfile = %s,pcv lost", AX->antnam, AX->antnum, DLY.mTable.antpcv);
            fclose(in);
            return 0;
        }
        //convert from mm to m
        for (j = 0; j < nrow; j++)
            for (l = 0; l < ncol; l++)
                AX->pcv[isys][k][j][l] = AX->pcv[isys][k][j][l] * 1e-3;
    }
    if(strlen(AX->antnum) && -1 != index_string(SYS,AX->antnum[0])){
        /* satellite here */
        isys = index_string(SYS,AX->antnum[0]);
        for(int ifq = 0;ifq < nfreq[isys];ifq++){
            if(len_trim(AX->freq[isys][ifq]) == 0){
                /* there is no record for this frequnency in the antatx memory */
                if(AX->nfreq == 0) {
                    continue;
                }
                /* pco here */
                for(int i =0; i < 3;i++) {
                    AX->neu[isys][ifq][i] = AX->neu[isys][0][i];
                }
                /* pcv here */
                for(int i =0; i < 81;i++){
                    for(int j = 0; j < 30;j++){
                        AX->pcv[isys][ifq][i][j] = AX->pcv[isys][0][i][j];
                    }
                }
            }
        }
    }
    fclose(in);
    return 1;
}
